package com.zhouzhou.fastjava.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.cookie.ClientCookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie2;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.Date;

public abstract class Requests {

    private static final Logger logger = LoggerFactory.getLogger(Requests.class);

    private static final RequestConfig config = RequestConfig.custom()
            .setCookieSpec(CookieSpecs.STANDARD)
            .setSocketTimeout(10 * 1000)
            .setConnectTimeout(10 * 1000)
            .setConnectionRequestTimeout(30 * 1000)
            .build();

    private static TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

    private static SSLConnectionSocketFactory csf;

    static {
        SSLContext sslContext;
        try {
            sslContext = org.apache.http.ssl.SSLContexts.custom()
                    .loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        csf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    }

    public static HttpClientBuilder newHttpClientBuilder(CookieStore cookieStore) {
        return HttpClients
                .custom()
                .setUserAgent("Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36")
                .setMaxConnPerRoute(Integer.MAX_VALUE)
                .setMaxConnTotal(Integer.MAX_VALUE)
                .setDefaultCookieStore(cookieStore)
                .setDefaultRequestConfig(config)
//                .disableRedirectHandling()
                .setSSLSocketFactory(csf);
    }

    public static HttpClient newHttpClient(CookieStore cookieStore) {
        return newHttpClientBuilder(cookieStore)
                .build();
    }

    public static HttpClient DEFAULT_CLIENT = newHttpClient(new BasicCookieStore());

    public static MyHttpRequest get(String url) {
        return MyHttpRequest.get(DEFAULT_CLIENT, url);
    }

    public static MyHttpRequest post(String url) {
        return MyHttpRequest.post(DEFAULT_CLIENT, url);
    }

    public static String toString(HttpResponse httpResponse) {
        try {
            return EntityUtils.toString(httpResponse.getEntity());
        } catch (IOException e) {
            throw new HttpException(e);
        }
    }

    public static CookieStore toCookieStore(String cookies) {
        CookieStore cookieStore = new BasicCookieStore();
        if (StringUtils.isNotBlank(cookies)) {
            JSONArray cookieItems = JSON.parseArray(cookies);
            for (int i = 0; i < cookieItems.size(); i++) {
                JSONObject cookieJson = cookieItems.getJSONObject(i);
                BasicClientCookie2 cookie = new BasicClientCookie2(cookieJson.getString("name"), cookieJson.getString("value"));
                cookie.setDomain(cookieJson.getString("domain"));
                cookie.setExpiryDate(DateUtils.addYears(new Date(), 1));
                cookie.setPath(cookieJson.getString("path"));
                cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");
                cookieStore.addCookie(cookie);
            }
        }
        return cookieStore;
    }

    public static String toCookieString(CookieStore cookieStore) {
        return JSON.toJSONString(cookieStore.getCookies());
    }

}
